package cn.edu.gznu.wecampus.core.common.api;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;

import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.druid.util.StringUtils;

import cn.edu.gznu.wecampus.core.BusinessException;
import cn.edu.gznu.wecampus.core.common.entity.jpa.Role;
import cn.edu.gznu.wecampus.core.common.entity.jpa.User;
import cn.edu.gznu.wecampus.core.common.entity.jpa.UserRole;
import cn.edu.gznu.wecampus.core.common.repository.jpa.RoleRepository;
import cn.edu.gznu.wecampus.core.common.repository.jpa.UserRepository;
import cn.edu.gznu.wecampus.core.common.repository.jpa.UserRoleRepository;
import cn.edu.gznu.wecampus.core.web.FormVo;
import cn.edu.gznu.wecampus.core.web.IAddRest;
import cn.edu.gznu.wecampus.core.web.IEditRest;
import cn.edu.gznu.wecampus.core.web.IRemoveRest;
import cn.edu.gznu.wecampus.core.web.ISearch;
import cn.edu.gznu.wecampus.core.web.RestResponseElement;
import cn.edu.gznu.wecampus.core.web.RestResponseList;
import cn.edu.gznu.wecampus.core.web.SearchVo;
import cn.edu.gznu.wecampus.core.web.annotation.SearchParam;
import cn.edu.gznu.wisedu.entity.ldap.Member;
import cn.edu.gznu.wisedu.repository.ldap.MemberRepository;
import lombok.Getter;
import lombok.Setter;

@RestController
@RequestMapping("/api/common/user")
public class UserApi implements
	ISearch<User, String, UserApi.UserSearchVo>,
	IAddRest<User, String, UserApi.UserFormVo>,
	IEditRest<User, String, UserApi.UserFormVo>,
	IRemoveRest<User, String> {
	
	@Autowired
	private MemberRepository memberRepository;
	
	@Autowired
	private UserRoleRepository userRoleRepository;
	
	@Autowired
	private RoleRepository roleRepository;

	@Getter
	@Setter
	public static class UserSearchVo extends SearchVo<User, String> {
		@SearchParam(fields = {"username", "realname"}, operator = "like")
		private String name;
	}

	@Getter
	@Setter
	public static class UserFormVo extends FormVo<String> {
		@NotEmpty(message = "用户名不能为空")
		private String username;
		@NotEmpty(message = "姓名不能为空")
		private String realname;
		private String password;
	}

	@Override
	public void processAddEntity(@Valid UserFormVo form, User entity) throws Exception {
		if(StringUtils.isEmpty(form.getPassword())) {
			throw new BusinessException("密码不能为空");
		}
		entity.setUsername(form.getUsername());
		entity.setRealname(form.getRealname());
		entity.setPasswordHex(new SimpleHash("sha-1", form.getPassword(), null, 1).toHex());
		this.getRepository().saveAndFlush(entity);
	}

	@Override
	public void processEditEntity(@Valid UserFormVo form, User entity) throws Exception {
		entity.setUsername(form.getUsername());
		entity.setRealname(form.getRealname());
		if(!StringUtils.isEmpty(form.getPassword())) {
			entity.setPasswordHex(new SimpleHash("sha-1", form.getPassword(), null, 1).toHex());
		}
		this.getRepository().saveAndFlush(entity);
	}

	@Override
	public void processRemoveEntity(User entity) {
		this.getRepository().delete(entity);
	}
	
	@PostMapping("addWiseduUsers")
	@Transactional
	public RestResponseList addWiseduUsers(@RequestParam("xghs") List<String> xghs) {
		UserRepository repository = (UserRepository) this.getRepository();
		List<User> users = xghs.stream()
			.filter(xgh -> repository.findByUsername(xgh) == null)
			.map(xgh -> {
				Member member = memberRepository.findByXgh(xgh);
				User user = new User();
				user.setUsername(member.getUid());
				user.setRealname(member.getCommonName());
				user.setPasswordHex(new SimpleHash("sha-1", member.getUid(), null, 1).toHex());
				repository.saveAndFlush(user);
				return user;
			}).collect(Collectors.toList());
		return this.createRestResponseList(users);
	}
	
	@Getter
	@Setter
	public static class AssginRolesFormVo extends FormVo<String> {
		private List<String> roleIds = new LinkedList<String>();
	}

	@PostMapping("assignRoles")
	@Transactional
	public RestResponseElement assignRoles(@Valid @RequestBody AssginRolesFormVo form) {
		User user = this.getRepository().findOne(form.getId());
		userRoleRepository.deleteAll(userRoleRepository.findByUser(user));
		form.getRoleIds().forEach(roleId -> {
			Role role = roleRepository.findOne(roleId);
			UserRole userRole = new UserRole();
			userRole.setUser(user);
			userRole.setRole(role);
			userRoleRepository.saveAndFlush(userRole);
		});
		return this.createRestResponseElement(user);
	}
}
